# Enhanced English-only startup script for quant backend
# This script avoids any non-ASCII characters and uses robust error handling

# Script configuration
$scriptPath = $PSScriptRoot
$logFile = Join-Path $scriptPath "startup_log.txt"
$celeryWorkerLog = Join-Path $scriptPath "celery_worker.log"
$celeryBeatLog = Join-Path $scriptPath "celery_beat.log"
$daphnePort = 8001

# Ensure we're in the script directory
Set-Location $scriptPath

# Create log file or clear existing one
if (Test-Path $logFile) {
    Clear-Content $logFile
} else {
    New-Item -Path $logFile -ItemType File -Force | Out-Null
}

# Enhanced logging function
function Write-Log {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Message,
        
        [Parameter(Mandatory=$false)]
        [ValidateSet("INFO", "WARNING", "ERROR")]
        [string]$Level = "INFO"
    )
    
    $time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logMessage = "[$time] [$Level] $Message"
    
    # Output to console with color
    switch ($Level) {
        "INFO"    { Write-Host $logMessage -ForegroundColor White }
        "WARNING" { Write-Host $logMessage -ForegroundColor Yellow }
        "ERROR"   { Write-Host $logMessage -ForegroundColor Red }
    }
    
    # Write to log file
    Add-Content -Path $logFile -Value $logMessage
}

# Function to check if a process is running
function Test-ProcessRunning {
    param($ProcessName)
    
    $process = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
    return ($null -ne $process)
}

# Function to check if a port is in use
function Test-PortInUse {
    param($Port)
    
    $connections = Get-NetTCPConnection -ErrorAction SilentlyContinue | 
                   Where-Object { $_.LocalPort -eq $Port -and $_.State -eq "Listen" }
    return ($null -ne $connections)
}

# Function to kill processes by name
function Stop-ProcessByName {
    param($ProcessName)
    
    try {
        $processes = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
        if ($processes) {
            Write-Log "Stopping existing $ProcessName processes" "INFO"
            Stop-Process -InputObject $processes -Force
            Start-Sleep -Seconds 2
        }
    } catch {
        Write-Log "Error stopping $ProcessName processes: $_" "ERROR"
    }
}

# Main script execution
try {
    Write-Log "Starting quant backend services" "INFO"
    Write-Log "Log file: $((Get-Item $logFile).FullName)" "INFO"
    
    # Check Redis service
    Write-Log "Checking Redis service" "INFO"
    $redis = Get-Service -Name Redis -ErrorAction SilentlyContinue
    
    if ($null -eq $redis) {
        Write-Log "Redis service not installed" "ERROR"
        Write-Log "Please install Redis and try again" "ERROR"
        exit 1
    }
    
    if ($redis.Status -ne "Running") {
        Write-Log "Redis service is not running, attempting to start" "WARNING"
        try {
            Start-Service Redis
            Start-Sleep -Seconds 2
            $redis.Refresh()
            if ($redis.Status -ne "Running") {
                throw "Failed to start Redis service"
            }
            Write-Log "Redis service started successfully" "INFO"
        } catch {
            Write-Log "Failed to start Redis service: $_" "ERROR"
            exit 1
        }
    } else {
        Write-Log "Redis service is running" "INFO"
    }
    
    # Check for existing Celery processes and stop them
    Write-Log "Checking for existing Celery processes" "INFO"
    Stop-ProcessByName "celery"
    
    # Check if port is in use
    if (Test-PortInUse $daphnePort) {
        Write-Log "Port $daphnePort is already in use" "WARNING"
        Write-Log "Attempting to free port $daphnePort" "INFO"
        
        $connections = Get-NetTCPConnection -LocalPort $daphnePort -State Listen
        foreach ($conn in $connections) {
            $process = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
            if ($process) {
                Write-Log "Stopping process using port $daphnePort - Name: $($process.ProcessName) (PID: $($process.Id))" "INFO"
                Stop-Process -Id $process.Id -Force
                Start-Sleep -Seconds 2
            }
        }
    }
    
    # Start Celery Worker
    Write-Log "Starting Celery Worker" "INFO"
    try {
        # Clear log file if it exists, or create it
        if (Test-Path $celeryWorkerLog) {
            Clear-Content $celeryWorkerLog
            Write-Log "Cleared existing Celery Worker log file" "INFO"
        } else {
            New-Item -Path $celeryWorkerLog -ItemType File -Force | Out-Null
            Write-Log "Created Celery Worker log file: $celeryWorkerLog" "INFO"
        }
        
        # Create a batch file to run Celery Worker
        $workerBatchFile = Join-Path $scriptPath "run_celery_worker.bat"
        @"
@echo off
cd /d "$scriptPath"
echo Starting Celery Worker at %date% %time% > "$celeryWorkerLog"
celery -A quant_back worker --pool=solo --loglevel=debug >> "$celeryWorkerLog" 2>&1
"@ | Out-File -FilePath $workerBatchFile -Encoding ascii
        
        Write-Log "Created Celery Worker batch file: $workerBatchFile" "INFO"
        
        # Start the process using the batch file
        $workerProcess = Start-Process -FilePath $workerBatchFile -PassThru -WindowStyle Hidden
        
        if ($null -eq $workerProcess) {
            throw "Failed to start Celery Worker"
        }
        Write-Log "Celery Worker started with PID: $($workerProcess.Id)" "INFO"
        Write-Log "Celery Worker log file: $celeryWorkerLog" "INFO"
        
        # Give it a moment to start writing to the log
        Start-Sleep -Seconds 2
    } catch {
        Write-Log "Error starting Celery Worker: $_" "ERROR"
        # Continue execution even if worker fails
    }
    
    # Start Celery Beat
    Write-Log "Starting Celery Beat" "INFO"
    try {
        # Clear log file if it exists, or create it
        if (Test-Path $celeryBeatLog) {
            Clear-Content $celeryBeatLog
            Write-Log "Cleared existing Celery Beat log file" "INFO"
        } else {
            New-Item -Path $celeryBeatLog -ItemType File -Force | Out-Null
            Write-Log "Created Celery Beat log file: $celeryBeatLog" "INFO"
        }
        
        # Create a batch file to run Celery Beat
        $beatBatchFile = Join-Path $scriptPath "run_celery_beat.bat"
        @"
@echo off
cd /d "$scriptPath"
echo Starting Celery Beat at %date% %time% > "$celeryBeatLog"
celery -A quant_back beat --loglevel=debug >> "$celeryBeatLog" 2>&1
"@ | Out-File -FilePath $beatBatchFile -Encoding ascii
        
        Write-Log "Created Celery Beat batch file: $beatBatchFile" "INFO"
        
        # Start the process using the batch file
        $beatProcess = Start-Process -FilePath $beatBatchFile -PassThru -WindowStyle Hidden
        
        if ($null -eq $beatProcess) {
            throw "Failed to start Celery Beat"
        }
        Write-Log "Celery Beat started with PID: $($beatProcess.Id)" "INFO"
        Write-Log "Celery Beat log file: $celeryBeatLog" "INFO"
        
        # Give it a moment to start writing to the log
        Start-Sleep -Seconds 2
    } catch {
        Write-Log "Error starting Celery Beat: $_" "ERROR"
        # Continue execution even if beat fails
    }
    
    # Start Daphne
    Write-Log "Starting Daphne server on port $daphnePort" "INFO"
    Write-Log "Press Ctrl+C to stop all services" "INFO"
    
    # Run Daphne in the foreground
    try {
        # This will block until Daphne exits
        daphne -p $daphnePort quant_back.asgi:application
    } catch {
        Write-Log "Error running Daphne: $_" "ERROR"
    }
    
} catch {
    Write-Log "Unexpected error: $_" "ERROR"
} finally {
    # Cleanup processes when script ends
    Write-Log "Stopping services" "INFO"
    
    if ($workerProcess -and -not $workerProcess.HasExited) { 
        Write-Log "Stopping Celery Worker (PID: $($workerProcess.Id))" "INFO"
        Stop-Process -Id $workerProcess.Id -Force -ErrorAction SilentlyContinue 
    }
    
    if ($beatProcess -and -not $beatProcess.HasExited) { 
        Write-Log "Stopping Celery Beat (PID: $($beatProcess.Id))" "INFO"
        Stop-Process -Id $beatProcess.Id -Force -ErrorAction SilentlyContinue 
    }
    
    # Also try to stop any remaining celery processes
    Stop-ProcessByName "celery"
    
    # Clean up batch files
    $workerBatchFile = Join-Path $scriptPath "run_celery_worker.bat"
    $beatBatchFile = Join-Path $scriptPath "run_celery_beat.bat"
    
    if (Test-Path $workerBatchFile) {
        Remove-Item $workerBatchFile -Force -ErrorAction SilentlyContinue
        Write-Log "Removed temporary worker batch file" "INFO"
    }
    
    if (Test-Path $beatBatchFile) {
        Remove-Item $beatBatchFile -Force -ErrorAction SilentlyContinue
        Write-Log "Removed temporary beat batch file" "INFO"
    }
    
    Write-Log "All services stopped" "INFO"
}